package com.cstor.liang.config;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.cstor.liang.mapper.AuthorityMapper;
import com.cstor.liang.mapper.RoleMapper;
import com.cstor.liang.mapper.UserMapper;
import com.cstor.liang.pojo.entity.Authority;
import com.cstor.liang.pojo.entity.Role;
import com.cstor.liang.pojo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Created by Administrator on 2017/9/1.
 */
public class AuthInterceptor implements HandlerInterceptor {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private AuthorityMapper authorityMapper;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        // 判断接口是否需要登录
        Auth auth = method.getAnnotation(Auth.class);
        if (auth != null) {
            // 执行用户认证
            String token = request.getHeader("Token");
            //禁止从请求参数里获取
//            if (token == null)
//                token = request.getParameter("Token");
            if (token == null)
                throw new RuntimeException("无token，请重新登录");

            String username = null;
            User user = null;
            try {
                //取出用户名
                DecodedJWT jwt = JWT.decode(token);
                username = jwt.getClaim("username").asString();
                //数据库查询用户信息
                Example example = new Example(User.class);
                example.createCriteria()
                        .andEqualTo("username", username)
                        .andEqualTo("isDelete", 0);
                List<User> list = userMapper.selectByExample(example);
                user = list.size() > 0 ? list.get(0) : null;
                if (null == user)
                    throw new RuntimeException("无效的Token");
                if (user.getEnabled() == 0)
                    throw new RuntimeException("用户已被禁止");
            } catch (JWTDecodeException exception) {
                //Invalid token
                throw new RuntimeException("无效的Token");
            }

            try {
                //验证 Token
                JWTVerifier verifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                verifier.verify(token);
            } catch (UnsupportedEncodingException exception) {
                //UTF-8 encoding not supported
                throw new RuntimeException("不支持UTF-8");
            } catch (JWTVerificationException exception) {
                //Invalid signature/claims
                throw new RuntimeException("Token验证错误");
            }

            //取出接口定义的角色类型
            String role = auth.role();
            //判断是否需要角色验证
            if (role != null && !role.equals("")){
                //取出当前用户的角色类型
                Role userRole = roleMapper.selectByPrimaryKey(user.getRoleId());
                if (userRole == null)
                    throw new RuntimeException("出错：请先给用户账号设置一个有效的角色类型");
                if (!userRole.getName().equals(role))
                    throw new RuntimeException("权限不足！");
            }
            //取出接口定义的权限
            String authority = auth.authority();
            //判断是否需要权限验证
            if (authority != null & !authority.equals("")){
                boolean success = false;
                //取出当前用户的所有权限
                List<Authority> list = authorityMapper.listByRoleId(user.getRoleId());
                for (Authority a : list){
                    if (a.getName().equals(authority))
                        success = true;
                }
                //判断权限是否满足
                if (!success)
                    throw new RuntimeException("权限不足！");
            }

            //至此，满足了用户认证、角色验证、权限验证

            request.setAttribute("user", user);
            request.getSession().setAttribute("user", user);
        }

        return true;
    }

    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
}
